package com.jeason.blogsearch.elasticsearch.service.impl;

import com.jeason.blogsearch.elasticsearch.domain.BlogSearchBean;
import com.jeason.blogsearch.elasticsearch.mapper.BlogSearchMapper;
import com.jeason.blogsearch.elasticsearch.service.ElasticService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 王欢
 * @date 2020/11/3 17:27
 */
@Slf4j
@Service
public class ElasticServiceImpl implements ElasticService {

    @Resource(name = "myRestHighLevelClient")
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    BlogSearchMapper blogSearchMapper;

    @Value("${elasticsearch.index}")
    private String index;
    @Value("${elasticsearch.source_field}")
    private String sourceField;

    @Override
    public boolean createIndex(String indexName) {
        try {
            XContentBuilder builder = XContentFactory.jsonBuilder()
                    .startObject()
                    .field("properties")
                    .startObject()
                    .field("goods_name").startObject().field("index", "true").field("type", "text").field("analyzer", "ik_max_word").field("search_analyzer", "ik_smart").endObject()
                    .field("id").startObject().field("index", "false").field("type", "text").endObject()
                    .field("goods_id").startObject().field("index", "false").field("type", "text").endObject()
                    .field("keyword").startObject().field("index", "true").field("type", "text").field("analyzer", "ik_max_word").field("search_analyzer", "ik_smart").endObject()
                    .field("create_time").startObject().field("index", "false").field("type", "text").endObject()
                    .field("modify_time").startObject().field("index", "false").field("type", "text").endObject()
                    .endObject()
                    .endObject();
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
            createIndexRequest.mapping(builder);
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
            if (createIndexResponse.isAcknowledged()) {
                return true;
            }
        } catch (IOException e) {
            log.error("创建映射关系失败:{}",e.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean indexExists(String indexName) {
        boolean exists = false;
        RestHighLevelClient restHighLevelClient = null;
        try {
            GetIndexRequest getIndexRequest = new GetIndexRequest(indexName);
            getIndexRequest.humanReadable(true);
            exists = restHighLevelClient.indices().exists(getIndexRequest,RequestOptions.DEFAULT);
        } catch (Exception e) {
            log.error("判断是否存索引在失败:{}",e.toString());
        }
        return exists;
    }

    @Override
    public boolean deleteIndex(String indexName) {
        boolean acknowledged = false;
        RestHighLevelClient restHighLevelClient = null;
        try {
            DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
            deleteIndexRequest.indicesOptions(IndicesOptions.LENIENT_EXPAND_OPEN);
            AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
            acknowledged = delete.isAcknowledged();
        } catch (Exception e) {
            log.error("删除索引失败:{}",toString());
        }
        return acknowledged;
    }


    @Override
    public List<Long> query(String keyword) throws IOException {
        //创建查询对象
        SearchRequest searchRequest = new SearchRequest(index);
        //创建搜索源对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //字段过滤
        searchSourceBuilder.fetchSource(sourceField.split(","), new String[]{});
        //创建条件匹配器
        MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "keyword").operator(Operator.OR);
        searchSourceBuilder.query(matchQueryBuilder);
        //设置查询条数
        searchSourceBuilder.size(100);
        //添加搜索源对象
        searchRequest.source(searchSourceBuilder);

        List<Long> goodsIdList = new ArrayList<>();
        //用客服端发起请求
        RestHighLevelClient restHighLevelClient = null;
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            //获取结果集
            SearchHits hits = searchResponse.getHits();
            //获取数据
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit searchHit : searchHits) {
                Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
                Object goodsId = sourceAsMap.get("goods_id");
                goodsIdList.add(Long.valueOf(goodsId.toString()));
            }
        } catch (Exception e) {
            log.error("搜索失败:{}",toString());
        }
        return goodsIdList;
    }

    @Override
    public void insertBatch(String idxName) {
        List<BlogSearchBean> list = blogSearchMapper.queryList();
        List<Map> maps = new ArrayList<>();
        for(BlogSearchBean i:list){
            Map<String,Object> map = new HashMap<>();
            map.put("id",i.getId());
            map.put("goods_id",i.getGoodsId());
            map.put("goods_name",i.getGoodsName());
            map.put("keyword",i.getKeyword());
            map.put("create_time",i.getCreateTime());
            map.put("modify_time",i.getModifyTime());
            maps.add(map);
        }
        BulkRequest request = new BulkRequest();
        maps.forEach(item -> request.add(new IndexRequest(idxName).id(item.get("id").toString())
                .source(item)));
        RestHighLevelClient restHighLevelClient = null;
        try {
            restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
